package com.huawang.mdesign.model.service.inter.diagram;

import com.huawang.business.constants.DirectEnum;
import com.huawang.business.constants.SimpleNavigationGroupEnum;
import com.huawang.business.dto.diagram.NewNodeDTO;
import com.huawang.business.dto.diagram.NewRelationDTO;
import com.huawang.business.dto.diagram.SimpleNavigation;
import com.huawang.business.dto.graph.ModelInfo;
import com.huawang.business.service.model.base.ElementModelInfoService;
import com.huawang.business.service.model.core.InternalUmlService;
import com.huawang.core.definition.mof.instances.MetaClassInstance;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SimpleNavigationService {

    @Autowired
    private InternalUmlService internalUmlService;

    @Autowired
    private ElementModelInfoService elementModelInfoService;

    @NotNull
    public List<NewNodeDTO> queryNewNode(@NotNull final String projectId,
                                         @NotNull final MetaClassInstance source,
                                         @NotNull final SimpleNavigation simpleNavigation,
                                         @NotNull final List<MetaClassInstance> elementMetaClass,
                                         @NotNull final Map<String, MetaClassInstance> simpleNavigationKeyInstanceMap) {
        if (Objects.equals(simpleNavigation.getType(), SimpleNavigationGroupEnum.RELATION.value())) {
            List<MetaClassInstance> ins = internalUmlService.queryRelationEndType(projectId, source, simpleNavigation.getKey(),
                    DirectEnum.IN.getName());
            if (CollectionUtils.isNotEmpty(elementMetaClass)) {
                ins = new ArrayList<>(CollectionUtils.intersection(elementMetaClass, ins));
            }

            List<NewNodeDTO> nodes = getNewNodesByMetaClass(projectId, ins, simpleNavigation, simpleNavigationKeyInstanceMap);
            List<MetaClassInstance> outs = internalUmlService.queryRelationEndType(projectId, source,
                    simpleNavigation.getKey(),
                    DirectEnum.OUT.getName());
            if (CollectionUtils.isNotEmpty(elementMetaClass)) {
                outs = (List<MetaClassInstance>) CollectionUtils.intersection(elementMetaClass, outs);
            }

            nodes.addAll(getNewNodesByMetaClass(projectId, outs, simpleNavigation, simpleNavigationKeyInstanceMap));
            return nodes;
        } else {
            String type = internalUmlService.queryPropertyTypeId(projectId, simpleNavigation.getKey());
            if (type == null) {
                return Collections.emptyList();
            }

            List<String> mClassListIds = internalUmlService.queryMetaClassByTypeUri(projectId, type);
            List<MetaClassInstance> mClassList = internalUmlService.fetchInstanceByIds(mClassListIds, projectId);
            if (CollectionUtils.isNotEmpty(elementMetaClass)) {
                mClassList =
                        new ArrayList<>(CollectionUtils.intersection(mClassList, elementMetaClass));
            }
            return getNewNodesByMetaClass(projectId, mClassList, simpleNavigation, simpleNavigationKeyInstanceMap);
        }

    }

    /**
     * 获取可创建节点列表
     *
     * @param projectId
     * @param metaClassList
     * @return java.util.List<com.huawang.mdesign.model.service.dto.diagram.NewNodeDto>
     * @author xz
     * @date 2022/07/12 19:15
     */
    @NotNull
    private List<NewNodeDTO> getNewNodesByMetaClass(String projectId, List<MetaClassInstance> metaClassList,
                                                    SimpleNavigation simpleNavigation,
                                                    @NotNull final Map<String, MetaClassInstance> simpleNavigationKeyInstanceMap) {
        MetaClassInstance simpleNavigationInstance = simpleNavigationKeyInstanceMap.get(simpleNavigation.getKey());
        return metaClassList.stream()
                .map(it -> {
                    if (BooleanUtils.isTrue(internalUmlService.getIsAbstract(projectId, it))) {
                        return null;
                    }

                    return createNewNode(projectId, elementModelInfoService.queryModelInfoByMetaClass(projectId, it), it.getId(),
                            simpleNavigation, simpleNavigationInstance);
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 根据modelInfo生成可创建新节点数据
     *
     * @param modelInfo
     * @param id
     * @param relationship
     * @return com.huawang.mdesign.model.service.dto.diagram.NewNodeDto
     * @author xz
     * @date 2022/07/12 19:14
     */
    @Nullable
    private NewNodeDTO createNewNode(@NotNull final String projectId,
                                     @Nullable final ModelInfo modelInfo,
                                     @NotNull final String id,
                                     @NotNull final SimpleNavigation navigation,
                                     @Nullable final MetaClassInstance relationship) {
        if (modelInfo == null) {
            return null;
        }

        NewNodeDTO in = new NewNodeDTO();
        in.setMetaclass(modelInfo.getMetaclass());
        in.setApplyStereotypes(modelInfo.getAppliedStereotypes());
        in.setIcon(modelInfo.getIcon());
        in.setLabel(modelInfo.getCnName());
        in.setMetaClassId(id);

        NewRelationDTO newRelationDto = new NewRelationDTO();
        newRelationDto.setKey(navigation.getKey());
        newRelationDto.setType(navigation.getType());
        newRelationDto.setLabel(navigation.getKey());
        if (navigation.getType().equals(SimpleNavigationGroupEnum.RELATION.value()) && relationship != null) {
            ModelInfo relationInfo = elementModelInfoService.queryModelInfoByMetaClass(projectId, relationship);
            if (relationInfo != null) {
                newRelationDto.setMetaclass(relationInfo.getMetaclass());
                newRelationDto.setApplyStereotypes(relationInfo.getAppliedStereotypes());
                newRelationDto.setLabel(relationInfo.getCnName());
            }
        }

        in.setOutgoing(Collections.singletonList(newRelationDto));
        return in;
    }
}
